﻿using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;
using System.Web.Services.Description;
using Microsoft.CSharp;

namespace PmfWeb.Core.Utility
{
    ///<summary>
    /// 动态调用webService
    ///</summary>
    public class WebServiceHelper
    {
        /// <summary>
        /// 动态调用webService
        /// </summary>
        /// <param name="url">服务地址</param>
        /// <param name="methodName">方法名</param>
        /// <param name="paras">参数数值</param>
        /// <returns>WebService服务执行结果</returns>
        public static object InvokeService(string url,string methodName,object[] paras)
        {
            return InvokeService(url, null, methodName, paras);
        }

        /// <summary>
        /// 动态调用webService
        /// </summary>
        /// <param name="url">服务地址</param>
        /// <param name="className">类名</param>
        /// <param name="methodName">方法名</param>
        /// <param name="arges">参数数值</param>
        /// <returns>WebService服务执行结果</returns>
        public static object InvokeService(string url,string className,string methodName,object[] arges)
        {
            if (String.IsNullOrEmpty(className)) className = GetWsClassName(url);
            const string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
            try
            {
                WebClient client = new WebClient();
                Stream stream = client.OpenRead(String.Format("{0}?WSDL", url));
                ServiceDescription description = ServiceDescription.Read(stream);

                ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
                importer.AddServiceDescription(description,"","");
                CodeNamespace cn = new CodeNamespace(@namespace);

                CodeCompileUnit ccu = new CodeCompileUnit();
                ccu.Namespaces.Add(cn);
                importer.Import(cn, ccu);
                CSharpCodeProvider csc = new CSharpCodeProvider();

                ICodeCompiler icc = csc.CreateCompiler();

                CompilerParameters paras = new CompilerParameters();
                paras.GenerateExecutable = false;
                paras.GenerateInMemory = true;
                paras.ReferencedAssemblies.Add("System.dll");
                paras.ReferencedAssemblies.Add("System.XML.dll");
                paras.ReferencedAssemblies.Add("System.Web.Services.dll");
                paras.ReferencedAssemblies.Add("System.Data.dll");

                CompilerResults results = icc.CompileAssemblyFromDom(paras, ccu);
                if(results.Errors.HasErrors)
                {
                    StringBuilder str = new StringBuilder("");
                    foreach (CompilerError  error in results.Errors)
                    {
                        str.AppendLine(error.ToString());
                    }
                    throw new Exception(str.ToString());
                }
                Assembly assembly = results.CompiledAssembly;
                Type type = assembly.GetType(String.Format("{0}.{1}", @namespace, className), true, true);
                object obj = Activator.CreateInstance(type);
                MethodInfo method = type.GetMethod(methodName);
                return method.Invoke(obj, arges);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.InnerException.Message,new Exception(ex.InnerException.StackTrace));
            }

        }

        private static string GetWsClassName(string wsUrl)
        {
            string[] parts = wsUrl.Split('/');
            string[] pps = parts[parts.Length - 1].Split('.');
            return pps[0];
        }

    }
}
